#include "EventLoop.h"
#include "Logger.h"
#include "Poller.h"
#include "Channel.h"

#include <sys/eventfd.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <memory>
__thread EventLoop *t_loopInThisThread = nullptr;

// 定义默认的Poller IO复用接口的超时时间
const int kPollTimeMs = 10000;

// 创建wakeupfd ，用来通知唤醒subReactor处理新来的channel
int createEventfd()
{
    int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (evtfd < 0)
    {
        LOG_FATAL("eventfd error:%d\n", errno);
    }
    return evtfd;
}

EventLoop::EventLoop()
    : looping_(false), quit_(false)
      // ,eventHandling_(false)
      ,
      callingPendingFunctors_(false)
      , threadId_(CurrentThread::tid())
      , poller_(Poller::newDefaultPoller(this))
      , wakeupChannel_(new Channel(this, wakeupFd_))
{
    LOG_DEBUG("EventLoop created %p in thread %d \n", this, threadId_);
    if (t_loopInThisThread)
    {
        LOG_FATAL("Another EventLoop %p exists in this thread %d \n", t_loopInThisThread, threadId_);
    }
    else
    {
        t_loopInThisThread = this;
    }
    // 设置wakeup fd的事件类型以及发生事件后回调操作
    // timestamp 参数传过去有什么用呢
    wakeupChannel_->setReadCallback(std::bind(&EventLoop::handleRead, this));
}

EventLoop::~EventLoop()
{
    // 对所有事件不感兴趣了
    wakeupChannel_->disableAll();
    // 把channel 从poller中移除
    wakeupChannel_->remove();
    ::close(wakeupFd_);
    t_loopInThisThread = nullptr;
}

// 在当前loop中执行cb
void EventLoop::runInloop(Functor cb)
{
    if (isInLoopThread()) // 在当前的loop线程中，执行cb
    {
        cb();
    }
    else // 在非当前loop线程中执行cb，那就需要唤醒loop所在线程，执行cb
    {
        queueInLoop(cb);
    }
}
// 把cb放入队列中，唤醒loop所在的线程，执行cb
void EventLoop::queueInLoop(Functor cb)
{
    {
        std::unique_lock<std::mutex> lock(mutex_);
        pendingFunctors_.emplace_back(cb); // 直接构造，push_back 拷贝构造
    }
    // 唤醒相应的，需要执行上面回调操作的loop的线程
    // callingPendingFunctors_的意思是：当前loop已经正在执行回调，但是loop又有了新的回调,
    //防止当前回调执行结束后睡眠
    if (!isInLoopThread() || callingPendingFunctors_)
    {
        wakeup(); // 唤醒loop所在线程
    }
}

void EventLoop::handleRead()
{
    uint64_t one = 1;
    ssize_t n = read(wakeupFd_, &one, sizeof one);
    if (n != sizeof one)
    {
        LOG_ERROR("EventLoop::handleRead() reads %d bytes instead of 8", n);
    }
}

void EventLoop::loop()
{
    looping_ = true;
    quit_ = false;
    LOG_INFO("EventLoop %p start looping \n", this);
    while (!quit_)
    {
        activeChannels_.clear();
        // 监听两类fd，一种是client的fd，一种wakeup fd
        pollReturnTime_ = poller_->poll(kPollTimeMs,&activeChannels_);
        for (Channel *channel : activeChannels_)
        {
            // poller 监听哪些channel发生事件了，然后上报给EventLoop，通知channel处理相应的事件
            channel->handleEvent(pollReturnTime_);
        }
        // 执行当前Eventloop事件循环需要处理的回调操作
        /**
         * IO线程 mainloop accept fd <= channel subloop 接受新用户的连接
         * main loop 事先注册一个回调cb(需要subloop执行) wakeup subloop后执行下面的方法，执行之前mainloop
         * 注册的cb 操作
         */
        doPendingFunctors();
    }
    LOG_INFO("EventLoop %p stop looping.\n", this);
    looping_ = false;
}
// 退出事件循环 1.loop在自己线程中调用quit  2.在非loop的线程中，调用loop的quit
/**
 *              mainloop
 *
 *                 直接通过wakeupFd通信               no ============生产者-消费者的线程安全的队列
 *
 * subLoop1     subLoop2     subLoop3
 */
void EventLoop::quit()
{
    quit_ = true;
    // 如果是在其他线程中，调用的quit  在一个subloop(worker)中，调用了mainLoop(IO)的quit
    if (!isInLoopThread())
    {
        wakeup();
    }
}

// 用来唤醒loop所在的线程的,向wakeupfd_写一个数据,wakeupChannel 就发生读事件，当前loop线程就会被唤醒
void EventLoop::wakeup()
{
    uint64_t one = 1;
    ssize_t n = write(wakeupFd_, &one, sizeof one);
    if (n != sizeof one)
    {
        LOG_ERROR("eventloop::wakeup() writes error!");
    }
}
// Eventloop的方法=》Poller的方法
void EventLoop::updateChannel(Channel *channel)
{
    poller_->updateChannel(channel);
}
void EventLoop::removeChannel(Channel *channel)
{
    poller_->removeChannel(channel);
}
bool EventLoop::hasChannel(Channel *channel)
{
    return poller_->hasChannel(channel);
}
void EventLoop::doPendingFunctors() // 执行回调
{
    std::vector<Functor> functors;
    callingPendingFunctors_ = true;
    {
        std::unique_lock<std::mutex> lock(mutex_);
        functors.swap(pendingFunctors_);
    }
    for (const Functor &functor : functors)
    {
        functor(); // 执行当前loop需要执行的回调操作
    }
    callingPendingFunctors_ = false;
}
